/**
  ******************************************************************************
  * @file    app_database.c
  * @author  tuancheng_Zero
  * @version V0.1
  * @date    08/28/2024
  * @brief   database operate manage module
  ******************************************************************************
*/ 
#include <includes.h>
#include "EEPROM_Driver.h"
#include "SRAM_Driver.h"
#include "app_Memory.h"
#include "Memory_cfg.h"

// 函数声明
DataMapAddr_ST * DataBase_GetMemoryMapAddr(uint16_t page, uint16_t pageAddr, uint16_t length);
static uint8_t DataBase_DataVaildCheck(uint32_t addr, uint8_t * dataPoint, uint16_t len, uint8_t type);
static void DataBase_DeviceControlInterface(uint16_t * sourData, uint32_t addr);
static uint8_t DataBase_GetPageSemaphore(uint32_t addr);
static uint8_t DataBase_PostPageSemaphore(uint32_t addr);

// 局部变量
static DataMapAddr_ST dataMapAddr_st = {0};
static const DataMapAddrTable_ST dataAddrMapTable[DataBase_UsedPageNum] = DataBaseAddrMapTable;
static const MemoryOperateCheck_ST BaseCheck_st = MemBaseCheckTable;
static const MemoryOperateCheck_ST NominalCheck_st = MemNominalCheckTable;
static const MemoryOperateCheck_ST SeriousAlarmCheck_st = MemSeriousAlarmCheckTable;
static const MemoryOperateCheck_ST PidDebugCheck_st = MemPidDebugCheckTable;
static const MemoryOperateCheck_ST MotorSwitchCheck_st = MemMotorSwitchCheckTable;
static const MemoryOperateCheck_ST FrontBackClosingCheck_st = MemF_BackClosingCheckTable;
static const MemoryOperateCheck_ST EstaMagnCheck_st = MemEstaMagnCheckTable;
static const MemoryOperateCheck_ST VolatilityCheck_st = MemVolatilityCheckTable;
static const MemoryOperateCheck_ST CeilingExciCheck_st = MemCeilingExciCheckTable;
static const MemoryOperateCheck_ST UnderFreqCheck_st = MemUnderFreqCheckTable;
static const MemoryOperateCheck_ST StartStopCheck_st = MemStartStopCheckTable;
static const MemoryOperateCheck_ST SyncClosingCheck_st = MemSyncClosingCheckTable;
static const MemoryOperateCheck_ST P100UploadCheck_st = MemP100_UploadCheckTable;
static const MemoryOperateCheck_ST P60UploadCheck_st = MemP60_UploadCheckTable;
static const MemoryOperateCheck_ST C60UploadCheck_st = MemC60_UploadCheckTable;
static const MemoryOperateCheck_ST SuddenUnloadCheck_st = MemSuddenUnloadCheckTable;
static const MemoryOperateCheck_ST CaliFactor_st = MemCaliFactorCheckTable;
static const MemoryOperateCheck_ST LoadEquCfg_st = MemLoadEquCfgTable;
static const MemoryOperateCheck_ST * cfgOperateCheck_st[DataBase_CfgPageUsedNum] = {&BaseCheck_st, &NominalCheck_st, &SeriousAlarmCheck_st, &PidDebugCheck_st, &MotorSwitchCheck_st, &FrontBackClosingCheck_st, &EstaMagnCheck_st, &VolatilityCheck_st, &CeilingExciCheck_st, &UnderFreqCheck_st, &StartStopCheck_st, &SyncClosingCheck_st, &P100UploadCheck_st, &P60UploadCheck_st, &C60UploadCheck_st, &SuddenUnloadCheck_st, &CaliFactor_st, &LoadEquCfg_st};
static const MemoryOperateCheck_ST DeviceControlCheck_st = MemDeviceControlCheckTable;
static const MemoryOperateCheck_ST ProcParameterCheck_st = MemProcParameterCheckTable;
static const MemoryOperateCheck_ST * tempConfigCheck_st[DataBase_TmpPageUsedNum] = {&DeviceControlCheck_st, &ProcParameterCheck_st};
static OS_EVENT * dbPageSem[DataBase_UsedPageNum - 2] = {0};
static OS_EVENT * cfgPageSem[DataBase_CfgPageUsedNum] = {0};
static OS_EVENT * tmpPageSem[DataBase_TmpPageUsedNum] = {0};

// 全局变量
ConfigMapAddrTable_ST cfgMapAddrTable[DataBase_CfgPageUsedNum] = DataBaseCfgAddrMapTable;
ConfigMapAddrTable_ST tmpCfgMapAddrTable[DataBase_TmpPageUsedNum] = DataBaseTmpCfgAddrMapTable;


/// @brief 数据库初始化
/// @param  none
void DataBase_Init(void){
    dbPageSem[0]   = App_Sem_DBPAGE0;
    dbPageSem[1]   = App_Sem_DBPAGE1;
    dbPageSem[2]   = App_Sem_DBPAGE2;
    dbPageSem[3]   = App_Sem_DBPAGE3;
    dbPageSem[4]   = App_Sem_DBPAGE4;
    dbPageSem[5]   = App_Sem_DBPAGE5;
    dbPageSem[6]   = App_Sem_DBPAGE6;
    dbPageSem[7]   = App_Sem_DBPAGE7;
    dbPageSem[8]   = App_Sem_DBPAGE8;
    cfgPageSem[0]  = App_Sem_CFGPAGE0;
    cfgPageSem[1]  = App_Sem_CFGPAGE1;
    cfgPageSem[2]  = App_Sem_CFGPAGE2;
    cfgPageSem[3]  = App_Sem_CFGPAGE3;
    cfgPageSem[4]  = App_Sem_CFGPAGE4;
    cfgPageSem[5]  = App_Sem_CFGPAGE5;
    cfgPageSem[6]  = App_Sem_CFGPAGE6;
    cfgPageSem[7]  = App_Sem_CFGPAGE7;
    cfgPageSem[8]  = App_Sem_CFGPAGE8;
    cfgPageSem[9]  = App_Sem_CFGPAGE9;
    cfgPageSem[10] = App_Sem_CFGPAGE10;
    cfgPageSem[11] = App_Sem_CFGPAGE11;
    cfgPageSem[12] = App_Sem_CFGPAGE12;
    cfgPageSem[13] = App_Sem_CFGPAGE13;
    cfgPageSem[14] = App_Sem_CFGPAGE14;
    cfgPageSem[15] = App_Sem_CFGPAGE15;
    cfgPageSem[16] = App_Sem_CFGPAGE16;
    cfgPageSem[17] = App_Sem_CFGPAGE17;
    tmpPageSem[0]  = App_Sem_TMPPAGE0;
    tmpPageSem[1]  = App_Sem_TMPPAGE1;
}

/// @brief 从数据库中读取内容
/// @param address 数据地址
/// @param dataBuff 存放缓冲区
/// @param length 读取长度(双字节)
/// @return 1成功   0失败
uint8_t DataBase_ReadDataContent(uint32_t address, uint16_t * dataBuff, uint16_t length){
    uint8_t os_err = 0;
    uint8_t status = DEF_FALSE;
    uint16_t page = 0;           // 页面号
    uint16_t pageAddr = 0;       // 页内地址
    DataMapAddr_ST * dataAddr_st = NULL;

    // 等待获取读写操作权限
    if(DataBase_GetPageSemaphore(address) == DEF_FALSE)
        return DEF_FALSE;
    // 获取内存地址
    page = (address >> 16);
    pageAddr = address;
    // 页面范围验证
    if(page > DataBase_UsedPageNum){
        goto READ_DATA_ERROR;
    }
    // 判断映射区类型
    dataAddr_st = DataBase_GetMemoryMapAddr(page, pageAddr, length);
    if(dataAddr_st == NULL){
        goto READ_DATA_ERROR;
    }
    // 从内存中读取
    if(dataAddr_st->dataArea == 1){
        memcpy((uint8_t *)dataBuff, dataAddr_st->ramAddrPoint, length * 2);
    }
    // 从SRAM中读取数据
    else if(dataAddr_st->dataArea == 2){
        // 等待SRAM读写操作权限
        OSSemPend((OS_EVENT *)App_Sem_DATABASERW,0,&os_err);
        if(SRAM_ReadData(dataAddr_st->sramAddr, (uint8_t *)dataBuff, length * 2) == DEF_FALSE){
            // 释放SRAM读写操作权限
            OSSemPost((OS_EVENT *)App_Sem_DATABASERW);
            goto READ_DATA_ERROR;
        }
        // 释放SRAM读写操作权限
        OSSemPost((OS_EVENT *)App_Sem_DATABASERW);
    }
    // 设置读取成功状态
    status = DEF_TRUE;
READ_DATA_ERROR:
    // 释放读写操作权限
    if(DataBase_PostPageSemaphore(address) == DEF_FALSE)
        return DEF_FALSE;
    return status;
}

/// @brief 往数据库中写入内容
/// @param address 数据地址
/// @param dataBuff 写入缓冲区
/// @param length 写入长度(单位:双字节)
/// @return 1成功   0失败
uint8_t DataBase_WriteDataContent(uint32_t address, uint16_t * dataBuff, uint16_t length){
    uint8_t os_err = 0;
    uint8_t status = DEF_FALSE;
    uint16_t page = 0;           // 页面号
    uint16_t pageAddr = 0;       // 页内地址
    DataMapAddr_ST * dataAddr_st = NULL;

    // 等待获取读写操作权限
    if(DataBase_GetPageSemaphore(address) == DEF_FALSE)
        return DEF_FALSE;
    // 获取内存地址
    page = (address >> 16);
    pageAddr = address;
    // 页面范围验证
    if(page > DataBase_MaxpageNum){
        goto WRITE_DATA_ERROR;
    }
    // 判断映射区类型
    dataAddr_st = DataBase_GetMemoryMapAddr(page, pageAddr, length);
    if(dataAddr_st == NULL){
        goto WRITE_DATA_ERROR;
    }
    // 往内存中写入数据
    if(dataAddr_st->dataArea == 1){
        memcpy(dataAddr_st->ramAddrPoint, (uint8_t *)dataBuff,  length * 2);
    }
    // 往SRAM中写入数据
    else if(dataAddr_st->dataArea == 2){
        // 等待SRAM读写操作权限
        OSSemPend((OS_EVENT *)App_Sem_DATABASERW,0,&os_err);
        if(SRAM_WriteData(dataAddr_st->sramAddr, (uint8_t *)dataBuff, length * 2) == DEF_FALSE){
            // 释放SRAM读写操作权限
            OSSemPost((OS_EVENT *)App_Sem_DATABASERW);
            goto WRITE_DATA_ERROR;
        }
        // 释放SRAM读写操作权限
        OSSemPost((OS_EVENT *)App_Sem_DATABASERW);
    }
    // 设置写入成功状态
    status = DEF_TRUE;
WRITE_DATA_ERROR:
    // 释放读写操作权限
    if(DataBase_PostPageSemaphore(address) == DEF_FALSE)
        return DEF_FALSE;
    return status;
}

/// @brief 通过协议从数据库中读取指定数据
/// @param sourData 需要解析的数据(格式：地址 + 长度 ...)
/// @param sourDataLen 数据长度
/// @param destData 解析数据存放缓冲
/// @param destDataLen 数据长度
/// @return 0失败  1成功
uint8_t DataBase_ProtocolContentRead(uint8_t *sourData, uint16_t sourDataLen, uint8_t *destData, uint16_t *destDataLen){
    if (sourDataLen == 0)
        return DEF_FALSE;
    if ((sourDataLen % NetWork_DataBase_OperatePack) != 0)
        return DEF_FALSE;

    uint8_t  datalength = 0;
    uint8_t *sourPoint = sourData, *destPoint = destData;
    uint16_t totalNumber = 0;
    uint32_t TempAddress = 0;
    uint32_t Length = sourDataLen;

    for (; Length > 0; Length -= NetWork_DataBase_OperatePack){
        // 数据地址
        sourPoint++;
        TempAddress  = (*(sourPoint++)) << 16;
        TempAddress |= (*(sourPoint++)) << 8;
        TempAddress |= (*(sourPoint++));
        // 数据长度
        datalength = *(sourPoint++);
        if (datalength == 0)
            return DEF_FALSE;
        // 页面范围判断
        if ((TempAddress & 0xff0000) != ((TempAddress + datalength) & 0xff0000))
            return DEF_FALSE;
        // 读取有效验证
        if(DataBase_DataVaildCheck(TempAddress, NULL, datalength, 0) == DEF_FALSE)
            return  DEF_FALSE;
        // 从数据库中获取数据
        if(DataBase_ReadDataContent(TempAddress, (uint16_t *)destPoint, datalength) == DEF_FALSE)
            return DEF_FALSE;
        destPoint += (datalength * 2);
        totalNumber += (datalength * 2);
    }
    *destDataLen = totalNumber;
    return DEF_TRUE;
}

/// @brief 通过协议往数据库中写入指定内容
/// @param sourData 需要解析的数据(格式：地址 + 长度 + 内容...)
/// @param sourDataLen 数据长度(单位：双字节)
/// @return 0失败  1成功
uint8_t DataBase_ProtocolContentWrite(uint8_t *sourData, uint16_t sourDataLen){
    if (sourDataLen == 0)
        return DEF_FALSE;
    if (sourDataLen <= NetWork_DataBase_OperatePack)
        return DEF_FALSE;
    uint8_t os_err = 0;
    uint8_t datalength;
    uint8_t eepromPage = 0;
    uint8_t *sourPoint = sourData;
    uint32_t TempAddress = 0;
    uint32_t Length = sourDataLen;

    for (; Length > 0; Length -= (NetWork_DataBase_OperatePack + (datalength * 2))){
        // 数据地址
        sourPoint++;
        TempAddress  = (*(sourPoint++)) << 16;
        TempAddress |= (*(sourPoint++)) << 8;
        TempAddress |= (*(sourPoint++));
        // 数据长度
        datalength = *(sourPoint++);
        if (datalength == 0)
            return DEF_FALSE;
        // 最大页面范围判断
        if ((TempAddress & 0xff0000) != ((TempAddress + datalength) & 0xff0000))
            return DEF_FALSE;
        // 写入有效验证
        if(DataBase_DataVaildCheck(TempAddress, sourPoint, datalength, 1) == DEF_FALSE)
            return DEF_FALSE;
        // 将数据写入数据库中
        if(DataBase_WriteDataContent(TempAddress, (uint16_t *)sourPoint, datalength) == DEF_FALSE)
            return DEF_FALSE;
        // 判断是否是参数配置页面
        if(((TempAddress >> 16) & 0xFF) == DB_PageDef_ParaCfgPage){
            eepromPage = (TempAddress >> 8) & 0xFF;
            // 触发信号量
            Memory_SetEEpromBit(eepromPage);
            // 发送EEPROM写入事件
            OSFlagPost(App_Flags_COMMON,OSCommFlags_UpdateCfg,OS_FLAG_SET,&os_err);
        }
        // 判断是否是临时配置
        else if(((TempAddress >> 16) & 0xFF) == DB_PageDef_TempConfigPage && TempAddress <= Addr_DeviceCtlTmp_TestProcess_order){
            DataBase_DeviceControlInterface((uint16_t *)sourPoint, TempAddress);
        }
        // 数据内容偏移
        sourPoint += (datalength * 2);
    }
    return DEF_TRUE;
}

/// @brief 获取内存映射地址
/// @param page 页面号
/// @param pageAddr 页面内地址
/// @param length 长度
/// @return 数据地址结构体
DataMapAddr_ST * DataBase_GetMemoryMapAddr(uint16_t page, uint16_t pageAddr, uint16_t length){
    uint8_t  dataArea = 0;
    uint16_t ramDataLen = 0;
    uint32_t sramStartAddr = 0;
    DataMapAddr_ST * dataAddr_st = NULL;

    ramDataLen = dataAddrMapTable[page].ramDataLen / 2;
    // 判断读取数据所在区域
    if(pageAddr < ramDataLen)
        dataArea = DataBase_DataArea_RAM;
    else
        dataArea = DataBase_DataArea_SRAM;
    // 在RAM区域
    if(dataArea == DataBase_DataArea_RAM && (page != DB_PageDef_ParaCfgPage && page != DB_PageDef_TempConfigPage)){
        // 判断数据范围合法性
        if((pageAddr + length) > ramDataLen)
            return NULL;
        // 判断RAM指针是否有效
        if(dataAddrMapTable[page].ramStartPoint == NULL)
            return NULL;
        // 将对应地址的指针偏移返回（RAM区可直接操作）
        dataMapAddr_st.ramAddrPoint = dataAddrMapTable[page].ramStartPoint + (pageAddr * 2);
        dataAddr_st = &dataMapAddr_st;
    }
    // 在SRAM区域
    else if(dataArea == DataBase_DataArea_SRAM && (page != DB_PageDef_ParaCfgPage && page != DB_PageDef_TempConfigPage)){
        // 判断数据范围合法性
        if((pageAddr + length) > (dataAddrMapTable[page].sramDataLen / 2))
            return NULL;
        // 判断SRAM指针是否有效
        if(dataAddrMapTable[page].ramStartPoint == NULL)
            return NULL;
        sramStartAddr = *(uint32_t *)dataAddrMapTable[page].sramStartPoint;
        // 获取偏移后的SRAM地址（SRAM区要先获取地址在操作）
        dataMapAddr_st.sramAddr = sramStartAddr + ((pageAddr - ramDataLen) * 2);
        dataAddr_st = &dataMapAddr_st;
    }
    // 在RAM的配置区
    else if(dataArea == DataBase_DataArea_RAM && (page == DB_PageDef_ParaCfgPage || page == DB_PageDef_TempConfigPage)){
        uint8_t cfgPage = 0;
        uint8_t cfgAddr = 0;
        ConfigMapAddrTable_ST * cfgAddrTable_st = (ConfigMapAddrTable_ST *)dataAddrMapTable[page].ramStartPoint;
        
        cfgPage = pageAddr >> 8;
        cfgAddr = pageAddr;
        // 判断页面范围合法性
        if(cfgPage > DataBase_CfgPageUsedNum && page == DB_PageDef_ParaCfgPage )
            return NULL;
        else if(cfgPage > DataBase_TmpPageUsedNum && page == DB_PageDef_TempConfigPage)
            return NULL;
        // 判断数据范围合法性
        if(cfgAddr + length > (cfgAddrTable_st[cfgPage].dataValidLength / 2))
            return NULL;
        // 将对应地址的指针偏移返回（RAM区可直接操作）
        dataMapAddr_st.ramAddrPoint = cfgAddrTable_st[cfgPage].sramStartPoint + (cfgAddr * 2);
        dataAddr_st = &dataMapAddr_st;
    }
    // 设置反馈区域
    dataMapAddr_st.dataArea = dataArea;
    // 返回地址结构体
    return dataAddr_st;
}

/// @brief 获取页面读写信号量
/// @param addr 地址
/// @return 0失败  1成功
static uint8_t DataBase_GetPageSemaphore(uint32_t addr){
    uint8_t os_err = 0;
    uint8_t page = addr >> 16;
    
    // 判断页面越界
    if(page > DataBase_UsedPageNum)
        return DEF_FALSE;
    // 匹配页面地址
    if(page == DB_PageDef_ParaCfgPage){
        page = addr >> 8;
        if(page >= DataBase_CfgPageUsedNum)
            return DEF_FALSE;
        // 等待获取读写操作权限
        OSSemPend((OS_EVENT *)cfgPageSem[page],0,&os_err);
    }
    else if (page == DB_PageDef_TempConfigPage){
        page = addr >> 8;
        if(page >= DataBase_TmpPageUsedNum)
            return DEF_FALSE;
        // 等待获取读写操作权限
        OSSemPend((OS_EVENT *)tmpPageSem[page],0,&os_err);
    }
    else{
        if(page >= (DataBase_UsedPageNum - 2))
            return DEF_FALSE;
        // 等待获取读写操作权限
        OSSemPend((OS_EVENT *)dbPageSem[page],0,&os_err);
    }
    return DEF_TRUE;
}

/// @brief 释放页面读写信号量
/// @param addr 地址
/// @return 0失败  1成功
static uint8_t DataBase_PostPageSemaphore(uint32_t addr){
    uint8_t page = addr >> 16;
    
    // 判断页面越界
    if(page > DataBase_UsedPageNum)
        return DEF_FALSE;
    // 匹配页面地址
    if(page == DB_PageDef_ParaCfgPage){
        page = addr >> 8;
        if(page >= DataBase_CfgPageUsedNum)
            return DEF_FALSE;
        // 释放读写操作权限
        OSSemPost((OS_EVENT *)cfgPageSem[page]);
    }
    else if (page == DB_PageDef_TempConfigPage){
        page = addr >> 8;
        if(page >= DataBase_TmpPageUsedNum)
            return DEF_FALSE;
        // 释放读写操作权限
        OSSemPost((OS_EVENT *)tmpPageSem[page]);
    }
    else{
        if(page >= (DataBase_UsedPageNum - 2))
            return DEF_FALSE;
        // 释放读写操作权限
        OSSemPost((OS_EVENT *)dbPageSem[page]);
    }
    return DEF_TRUE;
}

/// @brief 地址有效性验证
/// @param check_st 数据验证结构体
/// @param addr 地址
/// @param len 长度
/// @return 0失败  1成功
uint8_t DataBase_AddrVaildCheck(const MemoryOperateCheck_ST * check_st, uint16_t addr, uint16_t len){
    uint8_t  seekFlag = 0;
    uint16_t i = 0;
    uint16_t startAddr = addr;
    uint16_t endAddr   = addr + len;

    // 寻找开始地址和结束地址
    for(i = 0; i < check_st->itemNumber; i++){
        if(check_st->checkData_st[i].Addr == startAddr)
            seekFlag |= 0x01;
        if(check_st->checkData_st[i].Addr == endAddr)
            seekFlag |= (0x01 << 1);
        // 判断寻找结果
        if((seekFlag & 0x03) == 0x03)
            return DEF_TRUE;
    }
    return DEF_FALSE;
}

/// @brief 数据最大最小值范围验证
/// @param check_st 数据验证结构体
/// @param addr 地址
/// @param dataPoint 数据内容 
/// @param len 长度
/// @return 0失败  1成功
uint8_t DataBase_RangValidCheck(const MemoryOperateCheck_ST * check_st, uint16_t addr, uint8_t * dataPoint, uint16_t len){
    uint16_t i = 0, j = 0;
    uint16_t addrLength = 0;
    uint16_t startAddr = 0;
    uint16_t datalen = len;
    uint32_t  minValue_I = 0, maxValue_I = 0, setValue_I = 0;
    float32_t minValue_F = 0, maxValue_F = 0, setValue_F = 0;

    // 寻找写入开始地址
    for(i = 0; i < check_st->itemNumber; i++){
        if(check_st->checkData_st[i].Addr == addr){
            startAddr = i;
            break;
        }
    }
    // 判断从这个地址开始往后每个地址地最大最小值
    for(i = 0, j = 0; i < datalen; i += addrLength, j++){
        /* 判断是否有限制*/
        if(check_st->checkData_st[startAddr + j].rangLimit == MemCfg_RangLimit_OFF){
            dataPoint += check_st->checkData_st[startAddr + j].datalen;
            addrLength =  check_st->checkData_st[startAddr + j].datalen / 2;
            continue;
        }
        /* 判断是否是有权限 */
        if(check_st->checkData_st[startAddr + j].permission == MemCfg_Permission_R){
            return DEF_FALSE;
        }
        /* 整型数据 */
        if(check_st->checkData_st[startAddr + j].dataType == MemCfg_DataType_Integer){
            if(check_st->checkData_st[startAddr + j].datalen == 2)
                setValue_I = *(uint16_t *)dataPoint;
            else
                setValue_I = *(uint32_t *)dataPoint;
            minValue_I = check_st->checkData_st[startAddr + j].minValue_I;
            maxValue_I = check_st->checkData_st[startAddr + j].maxValue_I;
            // 如果检验失败直接退出
            if(setValue_I < minValue_I || setValue_I > maxValue_I)
                return DEF_FALSE;
        }
        /* 浮点数据 */
        else if(check_st->checkData_st[startAddr + j].dataType == MemCfg_Datatype_Float){
            memcpy(&setValue_F, dataPoint, sizeof(setValue_F));
            minValue_F = check_st->checkData_st[startAddr + j].minValue_F;
            maxValue_F = check_st->checkData_st[startAddr + j].maxValue_F;
            // 如果检验失败直接退出
            if(setValue_F < minValue_F || setValue_F > maxValue_F)
                return DEF_FALSE;
        }
        /* 数据偏移 */
        dataPoint += check_st->checkData_st[startAddr + j].datalen;
        addrLength =  check_st->checkData_st[startAddr + j].datalen / 2;
    }
    return DEF_TRUE;
}

/// @brief 数据有效性检查
/// @param addr 地址
/// @param len 长度
/// @param dataPoint 数据指针
/// @param type 操作类型 0读取  1写入
/// @return 1成功   0失败
static uint8_t DataBase_DataVaildCheck(uint32_t addr, uint8_t * dataPoint, uint16_t len, uint8_t type){
    uint8_t pageNum = 0;
    uint16_t pageAddr = 0;
    const MemoryOperateCheck_ST * dataCheck_st = NULL;

    pageNum = (addr >> 16) & 0xff; 
    pageAddr = addr & 0xffff;
    // 读取数据时除了参数配置，其余不做校验
    if(pageNum != DB_PageDef_ParaCfgPage && type == 0)
        return DEF_TRUE;
    // 只有参数配置和临时配置可以进行写操作
    if(type == 1 && (pageNum != DB_PageDef_ParaCfgPage && pageNum != DB_PageDef_TempConfigPage))
        return DEF_FALSE;
    // 参数配置页面
    if(pageNum == DB_PageDef_ParaCfgPage){
        if((pageAddr >> 8) > DataBase_CfgPageUsedNum)   // 判断地址页面数是否有效
            return DEF_FALSE;
        dataCheck_st = cfgOperateCheck_st[pageAddr >> 8];
    }
    // 临时配置页面
    else if(pageNum == DB_PageDef_TempConfigPage){
        if((pageAddr >> 8) > DataBase_TmpPageUsedNum)   //判断地址页面数是否有效
            return DEF_FALSE;
        dataCheck_st = tempConfigCheck_st[pageAddr >> 8];
    }
    // 地址有效校验
    if(DataBase_AddrVaildCheck(dataCheck_st, pageAddr, len) == DEF_FALSE)
        return DEF_FALSE;
    // 如果是数据读取无需继续判断
    if(type == 0)
        return DEF_TRUE;
    // 最大最小值范围判断
    if(DataBase_RangValidCheck(dataCheck_st, pageAddr, dataPoint, len) == DEF_FALSE)
        return DEF_FALSE;
    return DEF_TRUE;
}

/// @brief 设备控制接口函数
/// @param Cmd 控制命令
static void DataBase_DeviceControlInterface(uint16_t * sourData, uint32_t addr){
    uint8_t os_err;
    switch (addr)
    {
    case Addr_procParaTmp_ModifyDateTime:
        // 如果是配置时间则修改RTC配置
        rtc_TimeAdjust(*(uint32_t *)sourData);
        break;
    default:
        share_RemoteDataAddress_st.sourData=*sourData;
        share_RemoteDataAddress_st.addr=addr;
        OSFlagPost(App_Flags_WORKFLOW,OSWORKFLOWFlags_WithoutOrderHandleRequest,OS_FLAG_SET, &os_err);
        break;
    }
}

static uint16_t *SearchDataBasePageAddress(uint8_t PageNum)
{
	if(PageNum==0)   return(CommuniFakeConfig_Page0);
	if(PageNum==1)   return(CommuniFakeConfig_Page1);
	if(PageNum==220) return(CommuniFakeConfig_Page220);
	if(PageNum==221) return(CommuniFakeConfig_Page221);
	return(NULL);
}

/* Get 2Byte Data Content Value */
uint16_t GetDataBaseDataContent(uint16_t address)
{
	uint16_t TempData;
	
	if(ReadDataBaseDataContent(address, &TempData, 1))
	    return(TempData);
	else
		return(0);
}


/* Read Data Content Value */
uint8_t ReadDataBaseDataContent(uint16_t address, uint16_t *Buffer, uint8_t Number)
{
	uint8_t PageNum,Offset;
	uint16_t *Point;
	uint16_t *DataPoint;
	
	PageNum =(uint8_t)(address>>8);
	Offset  =(uint8_t) address;
	
	/* Get Page Address */
	Point = SearchDataBasePageAddress(PageNum);
	DataPoint = Point+Offset;
	
	for(; Number>0; Number--)
        *(Buffer++) = *(DataPoint++);
  
	return(DEF_TRUE);
}


/* Write Data Content Value */
uint8_t WriteDataBaseDataContent(uint16_t address, uint16_t *Buffer, uint8_t Number)
{
	uint8_t PageNum,Offset;
	uint16_t *Point;
    uint16_t *DataPoint;
	
	PageNum =(uint8_t)(address>>8);
	Offset  =(uint8_t) address;
	
	/* Get Page Address */
	Point=SearchDataBasePageAddress(PageNum);
	DataPoint = Point+Offset;
	
	for(; Number>0; Number--)
        *(DataPoint++) = *(Buffer++);
  
	return(DEF_TRUE);
}
